﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.ServiceModel.Syndication;
using System.Web.Hosting;
using ThirdPrize.Models;

namespace ThirdPrize.Classes
{
    public class TagCloud
    {
        private List<SyndicationItem> _items;
        private List<string> _selectedTags = new List<string> { "Steve Albini", "Compilation", "Vampire Weekend", "Sonic Youth", "Neil Young", "Reissue", "Beastie Boys" };

        private int _maxTagCount;

        private int _link0Size=20;
        private int _link1Size=30;
        private int _link2Size=40;
        private int _link3Size=50;
        private int _link4Size=60;

        private TagCloudModel Model { get; set; }

        public TagCloudModel CreateModel(string topic)
        {
            Model=new TagCloudModel();
            Model.Topic = topic;

            string rssUrl = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, topic + ".xml");

            GetDataFromRssFeed(rssUrl);

            StringBuilder s =new StringBuilder("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"");
            s.Append("\"http://www.w3.org/TR/html4/loose.dtd\">");
            s.Append("<html lang=\"en\">");
            s.Append("<head>");
            s.Append("<style type=\"text/css\">");
            s.Append("p.margin{margin-top:10px;margin-bottom:10px;margin-right:10px;margin-left:10px;}* {-webkit-touch-callout: none; -webkit-user-select: none; }");
            s.Append(
                String.Format(
                    ".link0 a {{vertical-align:middle; text-decoration:none; color:#444444; font-size:{0}px;}} .link1 a {{vertical-align:middle; text-decoration:none; color:#333333; font-size:{1}px;}} .link2 a {{vertical-align:middle; text-decoration:none; color:#222222; font-size:{2}px;}} .link3 a {{vertical-align:middle; text-decoration:none; color:#111111; font-size:{3}px;}} .link4 a {{vertical-align:middle; text-decoration:none; color:#000000; font-size:{4}px;}}",
                    _link0Size, _link1Size, _link2Size, _link3Size, _link4Size));
            s.Append(
                String.Format(".selectedlink0 a {{vertical-align:middle; text-decoration:none; color:#ff0000; font-size:{0}px;}}.selectedlink1 a {{vertical-align:middle; text-decoration:none; color:#ff1111; font-size:{1}px;}}.selectedlink2 a {{vertical-align:middle; text-decoration:none; color:#ff2222; font-size:{2}px;}}.selectedlink3 a {{vertical-align:middle; text-decoration:none; color:#ff3333; font-size:{3}px;}}.selectedlink4 a {{vertical-align:middle; text-decoration:none; color:#ff4444; font-size:{4}px;}}",
                    _link0Size, _link1Size, _link2Size, _link3Size, _link4Size));

            s.Append(
                String.Format(".readlink0 a {{vertical-align:middle; text-decoration:none; color:#000000; font-size:{0}px;}}.readlink1 a {{vertical-align:middle; text-decoration:none; color:#000000; font-size:{1}px;}}.readlink2 a {{vertical-align:middle; text-decoration:none; color:#000000; font-size:{2}px;}}.readlink3 a {{vertical-align:middle; text-decoration:none; color:#000000; font-size:{3}px;}}.readlink4 a {{vertical-align:middle; text-decoration:none; color:#000000; font-size:{4}px;}} h1 {{color:#ABDB25; font-size:20px;text-align:center;}}",
                    _link0Size, _link1Size, _link2Size, _link3Size, _link4Size));

            s.Append("</style>");
            s.Append("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">");
            s.Append("</head>");
            s.Append("<body>");

            //add to the tag view
            List<string> keys = Model.TagsAndStories.Keys.ToList();
            keys.Sort();
            foreach (string aKey in keys)
            {
                List<Story> storyList;
                Model.TagsAndStories.TryGetValue(aKey, out storyList);
                string escapedKey = Uri.EscapeDataString(aKey);
                if (_selectedTags.Contains(aKey))
                {
                    s.Append(String.Format(@"<span id=""{0}"" class=""selectedlink{1}""><a href=""Stories?topic={2}&tag={3}"">{0}</a></span>  ", aKey,
                                           GetSize(Model.TagsAndStories[aKey].Count), topic, escapedKey));
                }
                else
                {
                    s.Append(String.Format(@"<span id=""{0}"" class=""link{1}""><a href=""Stories?topic={2}&tag={3}"">{0}</a></span>  ", aKey,
                                           GetSize(Model.TagsAndStories[aKey].Count), topic, escapedKey));
                }

                s.Append("  ");
            }

            s.Append("</body>");
            s.Append("</html>");

            Model.HTML = s.ToString();
            return Model;
        }

        private void GetDataFromRssFeed(string url)
        {
            //init variables
            Model.TagsAndStories = new Dictionary<string, List<Story>>();
            Model.AllStories=new List<Story>();

            using (var r = XmlReader.Create(url))
            {
                SyndicationFeed feed = SyndicationFeed.Load(r);
                _items = feed.Items.ToList();

                string s = "";
                if (feed.ElementExtensions.Count(p => p.OuterName == "tagDistribution") != 0)
                    s = feed.ElementExtensions.First(p => p.OuterName == "tagDistribution").GetObject<XElement>().Value;

                string[] ss = s.Split(',');
                _maxTagCount = Int32.Parse(ss[1]);

                //for each item in feed
                foreach (SyndicationItem item in _items)
                {
                    Story story = new Story();
                    if (item.ElementExtensions.Count(p => p.OuterName == "iconurl") != 0)
                        story.IconUrl = item.ElementExtensions.First(p => p.OuterName == "iconurl").GetObject<XElement>().Value;
                    story.Title = item.Title.Text;
                    story.Uri = item.Links[0].Uri;
                    story.PublishDate = item.PublishDate;

                    //process tags
                    string allTags = null;
                    if (item.ElementExtensions.Count(p => p.OuterName == "tags") != 0)
                        allTags = item.ElementExtensions.First(p => p.OuterName == "tags").GetObject<XElement>().Value;
                    if (allTags == "")
                    {
                        allTags = "Miscellaneous";
                    }

                    Model.AllStories.Add(story);
                    var splitTags = allTags.Split('|');
                    story.Tags = splitTags.ToList();

                    foreach (string splitTag in splitTags)
                    {
                        List<Story> storyList;
                        if (Model.TagsAndStories.TryGetValue(splitTag, out storyList))
                        {
                            storyList.Add(story);
                        }
                        else
                        {
                            storyList = new List<Story>();
                            storyList.Add(story);
                            Model.TagsAndStories.Add(splitTag, storyList);
                        }
                    }
                }
            }
        }

        private int GetSize(int noStories)
        {
            int result;

            if (noStories == 1)
            {
                result = 0;
            }
            else if (noStories <= _maxTagCount * .25)
            {
                result = 1;
            }
            else if (noStories <= _maxTagCount * .5)
            {
                result = 2;
            }
            else if (noStories <= _maxTagCount * .75)
            {
                result = 3;
            }
            else 
            {
                result = 4;
            }
            return result;
        }
    }
}